#include "TabWidget.h"
#include "ItemDelegate.h"



#include <ItemModel.h>
#include <CampaignItem.h>
#include <FileHandler.h>
#include <ItemDelegate.h>



#include <QTabBar>
#include <QLineEdit>
#include <QTreeView>
#include <QHeaderView>
#include <QMessageBox>
#include <QFile>
#include <QFileDialog>
#include <QTimer>



TabWidget::TabWidget(QWidget *parent) :
    QTabWidget(parent)
{
    edit_index = -1;
}



void TabWidget::onNew(CampaignItem *item)
{
    QTreeView* view = new QTreeView(this);
    view->setItemDelegate(new ItemDelegate(this));

    if (!item) item = new CampaignItem("New Campaign");

    view->setModel(new ItemModel(item, view));
    addTab(view, item->name());
    setCurrentWidget(view);

    QHeaderView* header = view->header();
    header->setResizeMode(QHeaderView::Stretch);

    onRefresh();
}



void TabWidget::onOpen()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open"), QDir::currentPath(), tr("Xml Files (*.xml)"));

    if (fileName.isEmpty()) return;


    CampaignItem* item = qobject_cast<CampaignItem*>(FileHandler::open(fileName));
    if (!item)
    {
        QMessageBox::information(0, tr("Open Failed"), tr("Failed to open campaign!"));
        return;
    }
    item->setFilePath(fileName);
    item->setDirty(false);

    onNew(item);
}



void TabWidget::onSave(int index)
{
    if (index < 0) index = currentIndex();

    QTreeView* view = qobject_cast<QTreeView*>(widget(index));
    if (!view) return;

    ItemModel* model = qobject_cast<ItemModel*>(view->model());
    if (!model) return;

    CampaignItem* item = qobject_cast<CampaignItem*>(model->rootItem());
    if (!item)
    {
        QMessageBox::information(0, tr("Invalid Campaign Name"), tr("Campaign does not exist!"));
        return;
    }

    QString fileName = item->filePath();
    if (!QFile::exists(fileName))
    {
        onSaveAs(index);
        return;
    }

    if (!FileHandler::save(fileName, item))
    {
        QMessageBox::information(0, tr("Save Failed"), tr("Failed to save campaign!"));
    }

    item->setDirty(false);
}



void TabWidget::onSaveAs(int index)
{
    if (index < 0) index = currentIndex();

    QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), QDir::currentPath(), tr("Xml Files (*.xml)"));

    if (fileName.isEmpty()) return;

    QTreeView* view = qobject_cast<QTreeView*>(widget(index));
    if (!view) return;

    ItemModel* model = qobject_cast<ItemModel*>(view->model());
    if (!model) return;

    CampaignItem* item = qobject_cast<CampaignItem*>(model->rootItem());
    if (!item)
    {
        QMessageBox::information(0, tr("Invalid Campaign Name"), tr("Campaign does not exist!"));
        return;
    }

    if (!FileHandler::save(fileName, item))
    {
        QMessageBox::information(0, tr("Save Failed"), tr("Failed to save campaign!"));
    }

    item->setFilePath(fileName);
    item->setDirty(false);
}



void TabWidget::onClose(int index)
{
    if (index < 0) index = currentIndex();


    QTreeView* view = tabView(index);
    if (!view) return;

    ItemModel* model = dynamic_cast<ItemModel*>(view->model());
    if (!model) return;

    ItemGroup* root = model->rootItem();
    if (!root || !root->isDirty())
    {
        removeTab(index);
        return;
    }


    int q = QMessageBox::question(0,
                                 tr("Save Changed?"),
                                 tr("Campaign has changed. Do you want to save it?"),
                                 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);

    switch (q)
    {
    case QMessageBox::Cancel:
        return;

    case QMessageBox::No:
        break;

    case QMessageBox::Yes:
        onSave(index);
        break;
    }

    removeTab(index);
}



void TabWidget::onAddGroup(int index)
{
    QTreeView* view = tabView(index);

    if (!view) return;

    ItemModel* model = qobject_cast<ItemModel*>(view->model());
    if (!model) return;

    model->insertRow(0, QModelIndex());
    onRefresh();

}



void TabWidget::onAddItem(int index)
{
    QModelIndex itemIndex = tabView(index)->currentIndex();

    QObject* obj = static_cast<QObject*>(itemIndex.internalPointer());
    AbstractItem* item = dynamic_cast<AbstractItem*>(obj);
    if (!item) return;

    switch (item->category())
    {
    case ItemCategory_Group:
        break;
    case ItemCategory_Item:
        itemIndex = tabView()->model()->parent(itemIndex);
        break;
    case ItemCategory_Reference:
        itemIndex = tabView()->model()->parent(itemIndex);
        itemIndex = tabView()->model()->parent(itemIndex);
        break;
    default:
        return;
    }


    if (!itemIndex.isValid()) return;

    ItemModel* model = qobject_cast<ItemModel*>(tabView()->model());
    model->insertRow(0, itemIndex);
    onRefresh();
}



void TabWidget::onAddReference(int index)
{
    QModelIndex itemIndex = tabView(index)->currentIndex();

    QObject* obj = static_cast<QObject*>(itemIndex.internalPointer());
    AbstractItem* item = dynamic_cast<AbstractItem*>(obj);
    if (!item) return;

    switch (item->category())
    {
    case ItemCategory_Item:
        break;
    case ItemCategory_Reference:
        itemIndex = tabView()->model()->parent(itemIndex);
        break;
    default:
        return;
    }

    if (!itemIndex.isValid()) return;

    ItemModel* model = qobject_cast<ItemModel*>(tabView()->model());
    model->insertRow(0, itemIndex);
    onRefresh();
}



void TabWidget::onRefresh()
{
    QTreeView* view = tabView();
    if (!view) return;

    QHeaderView* header = view->header();
    if (!header) return;

    header->setResizeMode(AbstractItem::NameData, QHeaderView::ResizeToContents);

    QTimer::singleShot(0, this, SLOT(onRelease()));
}



void TabWidget::onRelease()
{
    QTreeView* view = tabView();
    QHeaderView* header = view->header();
    if (!header) return;

    header->setResizeMode(QHeaderView::Interactive);
}



void TabWidget::onBeginRename(int index)
{
    if (index < 0) index = currentIndex();

    QTabBar* tab_bar = tabBar();
    if (!tab_bar) return;

    edit_index = index;

    QString name = tabText(index);
    setTabText(index, "");


    QLineEdit* le = qobject_cast<QLineEdit*>(tab_bar->tabButton(edit_index, QTabBar::LeftSide));
    if (!le)
    {
        le = new QLineEdit(name);
        tab_bar->setTabButton(index, QTabBar::LeftSide, le);

    }
    le->show();
    le->setFocus();
    le->selectAll();

    connect(le, SIGNAL(editingFinished()), this, SLOT(onEndRename()));
}



void TabWidget::onEndRename()
{
    int index = edit_index;
    edit_index = -1;
    if (index < 0) return;

    QTabBar* tab_bar = tabBar();
    if (!tab_bar) return;

    QLineEdit* le = qobject_cast<QLineEdit*>(tab_bar->tabButton(index, QTabBar::LeftSide));
    if (!le) return;

    QString name = le->text();

    // remove line edit from tab
    tab_bar->setTabButton(index, QTabBar::LeftSide, 0);
    le->hide();
    le->deleteLater();

    if (name.simplified().isEmpty()) return;

    // set name to
    QTreeView* view = qobject_cast<QTreeView*>(widget(index));
    if (!view) return;

    ItemModel* model = qobject_cast<ItemModel*>(view->model());
    if (!model) return;

    AbstractItem* root = model->rootItem();
    root->setData(AbstractItem::NameData, name);

    setTabText(index, name);
}



QTreeView* TabWidget::tabView(int index)
{
    if (index < 0) index = currentIndex();

    return qobject_cast<QTreeView*>(widget(index));
}


